from flask import Flask, request, jsonify
import pymysql
import jwt
import time
import csv
import json
from dbutils.pooled_db import PooledDB
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes

tickets = {}

SECRET_KEY = "cqu_secret_key"
TOKEN_EXPIRATION_TIME = 3600  # 令牌有效时间（秒）


def read_csv(file_path):
    with open(file_path, "r") as file:
        reader = csv.reader(file)
        data = list(reader)
    return data


# 读取私钥
def load_private_key():
    with open("private_key.pem", "rb") as key_file:
        return serialization.load_pem_private_key(key_file.read(), password=None)


# 在应用启动时加载密钥
private_key = load_private_key()


# 连接mysql数据库
pool = PooledDB(
    creator=pymysql,  # 使用 PyMySQL 作为连接库
    maxconnections=50,  # 连接池中允许的最大连接数
    mincached=2,  # 启动时创建的空闲连接数量
    maxcached=5,  # 连接池中允许的最大空闲连接数
    blocking=True,  # 达到最大连接数后，阻塞而不是抛出错误
    host="10.242.160.16",
    user="wuliao",
    password="751216",
    db="BloodPressure",
)


def conn_mysql():
    return pymysql.connect(
        host="10.242.160.16", port=3306, user="******", password="******", database="BloodPressure", charset="utf8", connect_timeout=20
    )


# 提交数据
def insert_or_update_data(sql):
    conn = pool.connection()
    try:
        cursor = conn.cursor()
        cursor.execute(sql)
        conn.commit()  # 提交
    finally:
        cursor.close()
        conn.close()


app = Flask(__name__)


@app.route("/data", methods=["POST"])
def handle():
    auth_header = request.headers.get("Authorization")

    if not auth_header:
        return jsonify({"error": "Authorization header missing"}), 401

    token = auth_header.split(" ")[1]

    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        # 接收并解析客户端发送的加密数据（十六进制格式）
        encrypted_data_hex = request.json["data"]
        encrypted_data = bytes.fromhex(encrypted_data_hex)  # 将十六进制转换为字节流格式
        # 使用私钥解密数据
        decrypted_data = private_key.decrypt(
            encrypted_data, padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
        ).decode()
        # 将解密后的 JSON 字符串转换为字典
        original_data = json.loads(decrypted_data)
        sbp = original_data["sbp"]
        dbp = original_data["dbp"]
        id = original_data["id"]
        t = original_data["time"]
        h = original_data["h"]
        m = original_data["m"]
        print(sbp, dbp, id, t)
        sql = "INSERT INTO bp3 (time, h, m, sbp, dbp, device_id) VALUES ('{}', '{}', '{}', '{}', '{}', '{}')".format(t, h, m, sbp, dbp, id)
        insert_or_update_data(sql)
        # return "Data received"
        return jsonify({"message": "Access granted", "user": payload["sub"]}), 200
    except jwt.ExpiredSignatureError:
        return jsonify({"error": "Token expired"}), 401
    except jwt.InvalidTokenError:
        return jsonify({"error": "Invalid token"}), 401


def generate_access_token(username):
    payload = {"sub": username, "iat": time.time(), "exp": time.time() + TOKEN_EXPIRATION_TIME}
    token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
    return token


@app.route("/get_access_token", methods=["POST"])
def get_access_token():
    data = request.json
    ticket = data.get("ticket")

    if ticket in tickets:
        username = tickets[ticket]
        token = generate_access_token(username)
        return jsonify({"access_token": token}), 200
    else:
        return jsonify({"error": "Invalid ticket"}), 401


if __name__ == "__main__":
    ts = read_csv("tickets.csv")
    for t in ts:
        tickets[t[1]] = t[0]
    app.run(host="0.0.0.0", port=5000, debug=True, threaded=True)
